package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.catalina.User;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;


import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;
	@Autowired
	private WxMaService wxMaService;
	@Autowired
	private RedisTemplate redisTemplate;
	@Autowired
	private KafkaService kafkaService;
	@Autowired
	private UserPaidAlbumMapper userPaidAlbumMapper;
	@Autowired
	private UserPaidTrackMapper userPaidTrackMapper;
	@Autowired
	private TrackInfoFeignClient trackInfoFeignClient;
	@Autowired
	private UserVipServiceMapper userVipServiceMapper;
	@Autowired
	private VipServiceConfigMapper vipServiceConfigMapper;


	@Override
	public Map<String, Object> wxLogin(String code) {


			//通过code 获取openId 每个微信用户和对应一个openId
			String openid = null;
			try {
				//  需要将当前这个微信用户的appId，Secret 传入系统中.
				openid = wxMaService.jsCode2SessionInfo(code).getOpenid();
			} catch (WxErrorException e) {
				throw new RuntimeException(e);
			}

			//通过openId查询用户是否注册过
			UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openid));

			if (userInfo == null) {//实现注册功能

				 userInfo = new UserInfo();
				 userInfo.setWxOpenId(openid);
				 userInfo.setNickname("听友" + System.currentTimeMillis());
				 userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");

				 this.save(userInfo);

				 //参数一：topics  参数二：消息内容
				 kafkaService.sendMsg(KafkaConstant.QUEUE_USER_REGISTER,userInfo.getId().toString());

			}

			String token = UUID.randomUUID().toString().replaceAll("-","");

			String loginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;

			this.redisTemplate.opsForValue().set(loginKey,userInfo,RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);

			HashMap<String, Object> map = new HashMap<>();

			map.put("token",token);

			return map;

	}


	@Override
	public UserInfoVo getUserInfoVoByUserId(Long userId) {

		UserInfo userInfo = this.getById(userId);

		if (userInfo == null) {
			return null;
		}

		UserInfoVo userInfoVo = new UserInfoVo();

		BeanUtils.copyProperties(userInfo,userInfoVo);

		return userInfoVo;
	}


	@Override
	public Map<Long, Integer> userIsPaidTrack(Long userId, Long albumId, List<Long> trackIdList) {

		// 查看用户是否购买过专辑，如果购买过专辑，则需要付费的声音Id集合都需要免费.user_paid_album
		UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId));

		//select * from user_paid_track paid where user_id = ? and album_id = 1429 and track_id in (trackIdList);
		LambdaQueryWrapper<UserPaidTrack> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(UserPaidTrack::getUserId, userId).eq(UserPaidTrack::getAlbumId, albumId).in(UserPaidTrack::getTrackId, trackIdList);
		//  获取到当前这个用户购买过的声音Id列表
		List<Long> userPaidTrackIdList = userPaidTrackMapper.selectList(wrapper).stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());

		//  判断 trackIdList 这个集合中的声音Id 是否有购买过的声音Id
		Map<Long, Integer> map = new HashMap<>();
		for (Long trackId : trackIdList) {
			//  判断当前集合是否为空
			if (CollectionUtils.isEmpty(userPaidTrackIdList)) {
				//  0 要付费--true;
				map.put(trackId, 0);
			} else {
				//  判断 userPaidTrackIdList 集合中是否包含trackId
				if (userPaidTrackIdList.contains(trackId)) {
					//  1 免费--false
					map.put(trackId, 1);
				} else {
					//  0 要付费--true;
					map.put(trackId, 0);
				}
			}
		}
		return map;
	}


	@Override
	public Boolean isPaidAlbum(Long userId, Long albumId) {
		// 根据用户Id 与专辑Id 查询是否有记录
		Long count = userPaidAlbumMapper.selectCount(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId));
		if (count>0){
			return true;
		}
		return false;
	}


	@Override
	public List<Long> findUserPaidTrackList(Long albumId, Long userId) {

		return userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getAlbumId, albumId).eq(UserPaidTrack::getUserId, userId)).stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());

	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public void userPayRecord(UserPaidRecordVo userPaidRecordVo) {
		//  判断用户购买类型：1001
		        if (userPaidRecordVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_ALBUM)) {
		            //  先查询这个用户记录表中，是否已经存储数据了;
		            //  select * from user_paid_album where user_id = ? and album_id = ?;
		            //  根据订单编号查询是否有当前订单 select * from user_paid_album where order_no = ? ;
		            UserPaidAlbum userPaidAlbumQuery = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getOrderNo, userPaidRecordVo.getOrderNo()));
		            if (userPaidAlbumQuery != null) return;
		            //  购买专辑  user_paid_album
		            UserPaidAlbum userPaidAlbum = new UserPaidAlbum();
		            //  给属性赋值：
		            userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
		            userPaidAlbum.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
		            userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
		            userPaidAlbumMapper.insert(userPaidAlbum);

		        } else if (userPaidRecordVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_TRACK)) {
		            //  购买声音
		            Long count = userPaidTrackMapper.selectCount(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getOrderNo, userPaidRecordVo.getOrderNo()));
		            if (count != 0) return;
		            //  通过声音Id 获取声音对象;
		            Long trackId = userPaidRecordVo.getItemIdList().get(0);
		            //  找声音对象。
		            Result<TrackInfo> trackInfoResult = trackInfoFeignClient.getTrackInfoById(trackId);
		            TrackInfo trackInfo = trackInfoResult.getData();
		            //  保存数据
		            userPaidRecordVo.getItemIdList().forEach(itemId -> {
		                UserPaidTrack userPaidTrack = new UserPaidTrack();
		                userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
		                userPaidTrack.setUserId(userPaidRecordVo.getUserId());
		                userPaidTrack.setAlbumId(trackInfo.getAlbumId());
		                //  声音Id 对应的应该是一个集合.
		                userPaidTrack.setTrackId(itemId);
		                //  保存数据
		                userPaidTrackMapper.insert(userPaidTrack);
		            });

		        } else {
		            //  购买vip -- user_vip_service
		            //  根据订单编号查询数据
		            Long count = userVipServiceMapper.selectCount(new LambdaQueryWrapper<UserVipService>().eq(UserVipService::getOrderNo, userPaidRecordVo.getOrderNo()));
		            if (count != 0) return;
		            //  查询用户购买vip时间;
		            Long vipServiceConfigId = userPaidRecordVo.getItemIdList().get(0);
		            //  根据Id查询vip服务配置对象
		            VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(vipServiceConfigId);
		            Integer serviceMonth = vipServiceConfig.getServiceMonth();
		            //  创建对象
		            UserVipService userVipService = new UserVipService();
		            //  赋值：
		            userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
		            userVipService.setUserId(userPaidRecordVo.getUserId());
		            userVipService.setStartTime(new Date());
		            //  过期时间：
		            //  第一次购买当前时间+购买月份！  第二次购买可能会发生--续费： 当前过期时间+续费时间！
		            //  如何判断是否续费：是否vip and vip_expire > 当前系统时间
		            UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
		            //  判断
		            if (null != userInfo && userInfo.getIsVip() == 1 && userInfo.getVipExpireTime().after(new Date())){
		                //  userInfo.getVipExpireTime() + userInfo.getServiceMonth();
		                LocalDateTime localDate = new LocalDateTime(userInfo.getVipExpireTime());
		                Date expireTime = localDate.plusMonths(serviceMonth).toDate();
		                userVipService.setExpireTime(expireTime);
		            } else {
		                //  不是续费情况.
		                userVipService.setExpireTime(new LocalDate().plusMonths(serviceMonth).toDate());
		            }
		            //  保存数据
		            userVipServiceMapper.insert(userVipService);
		            //  普通用户变为vip 。user_info.is_vip = 1;
		            userInfo.setIsVip(1);
		            userInfo.setVipExpireTime(userVipService.getExpireTime());
		            userInfoMapper.updateById(userInfo);
		        }
	}


	@Override
	public void updateVipExpireStatus() {
		//  1.  查询哪些是vip失效的用户并将 is_vip 设置为 0;
		//  update user_info set is_vip = 0 where vip_expire_time < now() and is_vip = 1 and is_deleted = 0;
		userInfoMapper.updateVipExpireStatus();
	}
}
